/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Day10_Ex5_abstractColleciton;

// BasicCollection.java 
/* 
Demonstrates implementing a simple generic Collection<E>, 
using an inner class for the iterator. 
Stores the elements using a simple E[] array. 
We subclass off AbstractCollection, so we can inherit 
toString() and other convenience methods that are implemented 
in terms of basic Collection methods. 
The collection is "lame" since it crashes with more than 100 elements! 
 */
import java.util.*;

public class BasicCollection<E> extends AbstractCollection<E>
{

    public final static int SIZE = 100;
    private E[] array;
    private int length; // current logical length 

    // Creates an empty collection. 
    // @SuppressWarnings("unchecked") // how to get rid of warning 
    @SuppressWarnings("unchecked")
	public BasicCollection()
    {
        array = (E[]) new Object[SIZE];
        // The above line is an impossible case for the generics. 
        // Cannot say "new E[SIZE];" since, E does not exist at 
        //runtime. 
        // Best compromise new Object[SIZE] with (E[]) cast. 		
        // The cast is actually meaningless, since E is 		
        //erased to just Object at runtime. 

        length = 0;
    }

    // Adds an elements to the end. 
    public boolean add(E x)
    {
        array[length] = x;
        length++;
        return (true);
    }

    // Returns the current number of elements. 
    public int size()
    {
        return (length);
    }

    // Returns a new iterator at the beginning of the collection. 
    public Iterator<E> iterator()
    {
        return (new BasicIterator());
    }

    /* 
    Iterator implemented as a private inner class, so it has an implicit pointer to the outer BasicCollection object. So it can just refer to "length" and "array” to get the ivars of the outer BasicCollection= -- neato! Our internal state is "pre-advanced" – after the call to next(), our state is already advanced to point to the next element. In this way, hasNext() and next() are simplest. Tricky: class here is BasicIterator not BasicIterator<E>, since we are already in a scope where E is bound to something. 
     */
    private class BasicIterator implements Iterator<E>
    {

        private int index = 0; // next elem to return 

        // (not the one we just returned) 
        public boolean hasNext()
        {
            return (index < length); // nice: index is ours, length is the 				  
            //outer class' 
        }

        public E next()
        {
            E result = array[index];
            index++;
            return result;
        }

        public void remove()
        {
            /* this is an optional operation for iterators This is classic tricky array/boundary/off-by-one code -- make a drawing Move the array elements to the left one slot, starting at index arraycopy args: source, source index, dest, dest index, length. */

            System.arraycopy(array, index, array, index - 1, length - index);
            // Null out the last pointer to help the GC (optional) 

            array[length - 1] = null;
            // Move back both the length AND the iteration index 

            length--;
            index--;
        }
    }

    /*Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e)). This implementation iterates over the elements in the collection, checking each element in turn for equality with the specified element. */
    public boolean contains(Object o)
    {
        Iterator e = iterator();
        if (o == null)
        {
            while (e.hasNext())
            {
                if (e.next() == null)
                {
                    return true;
                }
            }
        } else
        {
            while (e.hasNext())
            {
                if (o.equals(e.next()))
                {
                    return true;
                }
            }
        }
        return false;
    }
}